home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / mig / dist / type.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-28  |  26.9 KB  |  1,018 lines

  1. /* 
  2.  * Mach Operating System
  3.  * Copyright (c) 1991,1990 Carnegie Mellon University
  4.  * All Rights Reserved.
  5.  * 
  6.  * Permission to use, copy, modify and distribute this software and its
  7.  * documentation is hereby granted, provided that both the copyright
  8.  * notice and this permission notice appear in all copies of the
  9.  * software, derivative works or modified versions, and any portions
  10.  * thereof, and that both notices appear in supporting documentation.
  11.  * 
  12.  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  13.  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  14.  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  15.  * 
  16.  * Carnegie Mellon requests users of this software to return to
  17.  * 
  18.  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
  19.  *  School of Computer Science
  20.  *  Carnegie Mellon University
  21.  *  Pittsburgh PA 15213-3890
  22.  * 
  23.  * any improvements or extensions that they make and grant Carnegie Mellon
  24.  * the rights to redistribute these changes.
  25.  */
  26. /*
  27.  * HISTORY
  28.  * $Log:    type.c,v $
  29.  * Revision 2.7  92/01/14  16:46:47  rpd
  30.  *     Changed Indefinite types from MustBeLong to ShouldBeLong.
  31.  *     Added itCheckFlags, itCheckDeallocate, itCheckIsLong.
  32.  *     Removed itServerCopy.
  33.  *     [92/01/09            rpd]
  34.  * 
  35.  * Revision 2.6  91/08/28  11:17:27  jsb
  36.  *     Removed itMsgKindType.
  37.  *     [91/08/12            rpd]
  38.  * 
  39.  * Revision 2.5  91/07/31  18:11:12  dbg
  40.  *     Indefinite-length inline arrays.
  41.  * 
  42.  *     Change itDeallocate to an enumerated type, to allow for
  43.  *     user-specified deallocate flag.
  44.  * 
  45.  *     Add itCStringDecl.
  46.  *     [91/07/17            dbg]
  47.  * 
  48.  * Revision 2.4  91/06/25  10:32:09  rpd
  49.  *     Changed itCalculateNameInfo to change type names from mach_port_t
  50.  *     to ipc_port_t for KernelServer and KernelUser interfaces.
  51.  *     [91/05/28            rpd]
  52.  * 
  53.  * Revision 2.3  91/02/05  17:56:02  mrt
  54.  *     Changed to new Mach copyright
  55.  *     [91/02/01  17:56:12  mrt]
  56.  * 
  57.  * Revision 2.2  90/06/02  15:05:54  rpd
  58.  *     Created for new IPC.
  59.  *     [90/03/26  21:14:07  rpd]
  60.  * 
  61.  * 07-Apr-89  Richard Draves (rpd) at Carnegie-Mellon University
  62.  *    Extensive revamping.  Added polymorphic arguments.
  63.  *    Allow multiple variable-sized inline arguments in messages.
  64.  *
  65.  * 17-Aug-88  Mary Thompson (mrt) at Carnegie-Mellon University
  66.  *    Removed translation of MSG_TYPE_INVALID as that type
  67.  *    is no longer defined by the kernel.
  68.  * 
  69.  * 19-Feb-88  Mary Thompson (mrt) at Carnegie-Mellon University
  70.  *    Changed itPrintTrans and itPrintDecl to reflect new translation syntax.
  71.  *    Changed itCheckDecl to set itServerType to itType if is is strNULL.
  72.  *
  73.  *  4-Feb-88  Mary Thompson (mrt) at Carnegie-Mellon University
  74.  *    Added a check to itCheckDecl to make sure that in-line
  75.  *    variable length arrays have a non-zero maximum length.
  76.  *
  77.  * 22-Dec-87  David Golub (dbg) at Carnegie-Mellon University
  78.  *    Removed warning message for translation.
  79.  *
  80.  * 16-Nov-87  David Golub (dbg) at Carnegie-Mellon University
  81.  *    Changed itVarArrayDecl to take a 'max' parameter for maximum
  82.  *    number of elements, and to make type not be 'struct'.
  83.  *    Added itDestructor.
  84.  *
  85.  * 18-Aug-87  Mary Thompson (mrt) at Carnegie-Mellon University
  86.  *    Added initialization of itPortType
  87.  *
  88.  * 14-Aug-87  Mary Thompson (mrt) at Carnegie-Mellon University
  89.  *    Added initialization for itTidType
  90.  *
  91.  * 15-Jun-87  David Black (dlb) at Carnegie-Mellon University
  92.  *    Fixed prototype for itAlloc; was missing itServerType field.
  93.  *
  94.  * 10-Jun-87  Mary Thompson (mrt) at Carnegie-Mellon University
  95.  *    Removed extern from procedure definitions to make hi-c happy
  96.  *    Changed the c type names of itDummyType from caddr_t to
  97.  *    char * and of itCountType from u_int to unsigned int to
  98.  *    eliminate the need to import sys/types.h into the mig generated
  99.  *    code.
  100.  *
  101.  * 28-May-87  Richard Draves (rpd) at Carnegie-Mellon University
  102.  *    Created.
  103.  */
  104.  
  105. #include <mach/message.h>
  106. #include "error.h"
  107. #include "alloc.h"
  108. #include "global.h"
  109. #include "type.h"
  110.  
  111. ipc_type_t *itRetCodeType;    /* used for return codes */
  112. ipc_type_t *itDummyType;    /* used for camelot dummy args */
  113. ipc_type_t *itTidType;        /* used for camelot tids */
  114. ipc_type_t *itRequestPortType;    /* used for default Request port arg */
  115. ipc_type_t *itZeroReplyPortType;/* used for dummy Reply port arg */
  116. ipc_type_t *itRealReplyPortType;/* used for default Reply port arg */
  117. ipc_type_t *itWaitTimeType;    /* used for dummy WaitTime args */
  118. ipc_type_t *itMsgOptionType;    /* used for dummy MsgOption args */
  119.  
  120. static ipc_type_t *list = itNULL;
  121.  
  122. /*
  123.  *  Searches for a named type.  We use a simple
  124.  *  self-organizing linked list.
  125.  */
  126. ipc_type_t *
  127. itLookUp(name)
  128.     identifier_t name;
  129. {
  130.     register ipc_type_t *it, **last;
  131.  
  132.     for (it = *(last = &list); it != itNULL; it = *(last = &it->itNext))
  133.     if (streql(name, it->itName))
  134.     {
  135.         /* move this type to the front of the list */
  136.         *last = it->itNext;
  137.         it->itNext = list;
  138.         list = it;
  139.  
  140.         return it;
  141.     }
  142.  
  143.     return itNULL;
  144. }
  145.  
  146. /*
  147.  *  Enters a new name-type association into
  148.  *  our self-organizing linked list.
  149.  */
  150. void
  151. itInsert(name, it)
  152.     identifier_t name;
  153.     ipc_type_t *it;
  154. {
  155.     it->itName = name;
  156.     it->itNext = list;
  157.     list = it;
  158. }
  159.  
  160. static ipc_type_t *
  161. itAlloc()
  162. {
  163.     static ipc_type_t prototype =
  164.     {
  165.     strNULL,        /* identifier_t itName */
  166.     0,            /* ipc_type_t *itNext */
  167.     0,            /* u_int itTypeSize */
  168.     0,            /* u_int itPadSize */
  169.     0,            /* u_int itMinTypeSize */
  170.     0,            /* u_int itInName */
  171.     0,            /* u_int itOutName */
  172.     0,            /* u_int itSize */
  173.     1,            /* u_int itNumber */
  174.     TRUE,            /* boolean_t itInLine */
  175.     FALSE,            /* boolean_t itLongForm */
  176.     d_NO,            /* dealloc_t itDeallocate */
  177.     strNULL,        /* string_t itInNameStr */
  178.     strNULL,        /* string_t itOutNameStr */
  179.     flNone,            /* ipc_flags_t itFlags */
  180.     TRUE,            /* boolean_t itStruct */
  181.     FALSE,            /* boolean_t itString */
  182.     FALSE,            /* boolean_t itVarArray */
  183.     FALSE,            /* boolean_t itIndefinite */
  184.     itNULL,            /* ipc_type_t *itElement */
  185.     strNULL,        /* identifier_t itUserType */
  186.     strNULL,        /* identifier_t itServerType */
  187.     strNULL,        /* identifier_t itTransType */
  188.     strNULL,        /* identifier_t itInTrans */
  189.     strNULL,        /* identifier_t itOutTrans */
  190.     strNULL,        /* identifier_t itDestructor */
  191.     };
  192.     register ipc_type_t *new;
  193.  
  194.     new = (ipc_type_t *) malloc(sizeof *new);
  195.     if (new == itNULL)
  196.     fatal("itAlloc(): %s", unix_error_string(errno));
  197.     *new = prototype;
  198.     return new;
  199. }
  200.  
  201. /*
  202.  * Convert an IPC type-name into a string.
  203.  */
  204. static char *
  205. itNameToString(name)
  206.     u_int name;
  207. {
  208.     char buffer[100];
  209.  
  210.     (void) sprintf(buffer, "%u", name);
  211.     return strmake(buffer);
  212. }
  213.  
  214. /*
  215.  * Calculate itTypeSize, itPadSize, itMinTypeSize.
  216.  * Every type needs this info; it is recalculated
  217.  * when itInLine, itNumber, or itSize changes.
  218.  */
  219. static void
  220. itCalculateSizeInfo(it)
  221.     register ipc_type_t *it;
  222. {
  223.     if (it->itInLine)
  224.     {
  225.     u_int bytes = (it->itNumber * it->itSize + 7) / 8;
  226.     u_int padding = (4 - bytes%4)%4;
  227.  
  228.     it->itTypeSize = bytes;
  229.     it->itPadSize = padding;
  230.     if (it->itVarArray)
  231.         it->itMinTypeSize = 0;
  232.     else
  233.         it->itMinTypeSize = bytes + padding;
  234.     }
  235.     else
  236.     {
  237.     /* out-of-line, so use size of pointers */
  238.     u_int bytes = sizeof(char *);
  239.  
  240.     it->itTypeSize = bytes;
  241.     it->itPadSize = 0;
  242.     it->itMinTypeSize = bytes;
  243.     }
  244.  
  245.     /* Unfortunately, these warning messages can't give a type name;
  246.        we haven't seen a name yet (it might stay anonymous.) */
  247.  
  248.     if ((it->itNumber * it->itSize) % 8 != 0)
  249.     warn("size of C types must be multiples of 8 bits");
  250.  
  251.     if ((it->itTypeSize == 0) && !it->itVarArray)
  252.     warn("sizeof(%s) == 0");
  253. }
  254.  
  255. /*
  256.  * Fill in default values for some fields used in code generation:
  257.  *    itInNameStr, itOutNameStr, itUserType, itServerType, itTransType
  258.  * Every argument's type should have these values filled in.
  259.  */
  260. static void
  261. itCalculateNameInfo(it)
  262.     register ipc_type_t *it;
  263. {
  264.     if (it->itInNameStr == strNULL)
  265.     it->itInNameStr = strmake(itNameToString(it->itInName));
  266.     if (it->itOutNameStr == strNULL)
  267.     it->itOutNameStr = strmake(itNameToString(it->itOutName));
  268.  
  269.     if (it->itUserType == strNULL)
  270.     it->itUserType = it->itName;
  271.     if (it->itServerType == strNULL)
  272.     it->itServerType = it->itName;
  273.  
  274.     /*
  275.      *    KernelServer and KernelUser interfaces get special treatment here.
  276.      *    On the kernel side of the interface, ports are really internal
  277.      *    port pointers (ipc_port_t), not port names (mach_port_t).
  278.      *    At this point, we don't know if the argument is in or out,
  279.      *    so we don't know if we should look at itInName or itOutName.
  280.      *    Looking at both should be OK.
  281.      *
  282.      *    This is definitely a hack, but I think it is cleaner than
  283.      *    mucking with type declarations throughout the kernel .def files,
  284.      *    hand-conditionalizing on KERNEL_SERVER and KERNEL_USER.
  285.      */
  286.  
  287.     if (IsKernelServer &&
  288.     streql(it->itServerType, "mach_port_t") &&
  289.     (((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) &&
  290.       (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)) ||
  291.      MACH_MSG_TYPE_PORT_ANY(it->itInName) ||
  292.      MACH_MSG_TYPE_PORT_ANY(it->itOutName)))
  293.     it->itServerType = "ipc_port_t";
  294.  
  295.     if (IsKernelUser &&
  296.     streql(it->itUserType, "mach_port_t") &&
  297.     (((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) &&
  298.       (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)) ||
  299.      MACH_MSG_TYPE_PORT_ANY(it->itInName) ||
  300.      MACH_MSG_TYPE_PORT_ANY(it->itOutName)))
  301.     it->itUserType = "ipc_port_t";
  302.  
  303.     if (it->itTransType == strNULL)
  304.     it->itTransType = it->itServerType;
  305. }
  306.  
  307. ipc_flags_t
  308. itCheckFlags(flags, name)
  309.     ipc_flags_t flags;
  310.     identifier_t name;
  311. {
  312.     /* only one of flLong and flNotLong */
  313.  
  314.     if ((flags&(flLong|flNotLong)) == (flLong|flNotLong)) {
  315.     warn("%s: IsLong and IsNotLong cancel out", name);
  316.     flags &= ~(flLong|flNotLong);
  317.     }
  318.  
  319.     /* only one of flDealloc, flNotDealloc, flMaybeDealloc */
  320.  
  321.     if (flags & flMaybeDealloc) {
  322.     if (flags & (flDealloc|flNotDealloc)) {
  323.         warn("%s: Dealloc and NotDealloc ignored with Dealloc[]", name);
  324.         flags &= ~(flDealloc|flNotDealloc);
  325.     }
  326.     }
  327.  
  328.     if ((flags&(flDealloc|flNotDealloc)) == (flDealloc|flNotDealloc)) {
  329.     warn("%s: Dealloc and NotDealloc cancel out", name);
  330.     flags &= ~(flDealloc|flNotDealloc);
  331.     }
  332.  
  333.     return flags;
  334. }
  335.  
  336. dealloc_t
  337. itCheckDeallocate(it, flags, dfault, name)
  338.     register ipc_type_t *it;
  339.     ipc_flags_t flags;
  340.     dealloc_t dfault;
  341.     identifier_t name;
  342. {
  343.     dealloc_t dealloc = dfault;
  344.  
  345.     if (flags & flMaybeDealloc)
  346.     dealloc = d_MAYBE;
  347.     if (flags & flDealloc)
  348.     dealloc = d_YES;
  349.     if (flags & flNotDealloc)
  350.     dealloc = d_NO;
  351.  
  352.     if (dealloc == dfault) {
  353.     if (flags & flMaybeDealloc)
  354.         warn("%s: Dealloc[] is redundant", name);
  355.     if (flags & flDealloc)
  356.         warn("%s: Dealloc is redundant", name);
  357.     if (flags & flNotDealloc)
  358.         warn("%s: NotDealloc is redundant", name);
  359.     }
  360.  
  361.     if (flags & (flMaybeDealloc|flDealloc|flNotDealloc)) {
  362.     /* only give semantic warnings if the user specified something */
  363.  
  364.     if (dealloc != d_NO) {
  365.         if (it->itInLine && !it->itIndefinite)
  366.         warn("%s: Dealloc will cause an IPC error", name);
  367.     }
  368.     }
  369.  
  370.     return dealloc;
  371. }
  372.  
  373. static enum uselong { NotLong, CanBeLong, ShouldBeLong, MustBeLong, TooLong }
  374. itUseLong(it)
  375.     register ipc_type_t *it;
  376. {
  377.     enum uselong uselong = NotLong;
  378.  
  379.     if ((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) ||
  380.     (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC) ||
  381.     it->itVarArray)
  382.     uselong = CanBeLong;
  383.  
  384.     if ((it->itVarArray && !it->itInLine) || it->itIndefinite)
  385.     uselong = ShouldBeLong;
  386.  
  387.     if (((it->itInName != MACH_MSG_TYPE_POLYMORPHIC) &&
  388.      (it->itInName >= (1<<8))) ||
  389.     ((it->itOutName != MACH_MSG_TYPE_POLYMORPHIC) &&
  390.      (it->itOutName >= (1<<8))) ||
  391.     (it->itSize >= (1<<8)) ||
  392.     (it->itNumber >= (1<<12)))
  393.     uselong = MustBeLong;
  394.  
  395.     if (((it->itInName != MACH_MSG_TYPE_POLYMORPHIC) &&
  396.      (it->itInName >= (1<<16))) ||
  397.     ((it->itOutName != MACH_MSG_TYPE_POLYMORPHIC) &&
  398.      (it->itOutName >= (1<<16))) ||
  399.     (it->itSize >= (1<<16)))
  400.     uselong = TooLong;
  401.  
  402.     return uselong;
  403. }
  404.  
  405. boolean_t
  406. itCheckIsLong(it, flags, dfault, name)
  407.     register ipc_type_t *it;
  408.     ipc_flags_t flags;
  409.     boolean_t dfault;
  410.     identifier_t name;
  411. {
  412.     boolean_t islong = dfault;
  413.  
  414.     if (flags & flLong)
  415.     islong = TRUE;
  416.     if (flags & flNotLong)
  417.     islong = FALSE;
  418.  
  419.     if (islong == dfault) {
  420.     if (flags & flLong)
  421.         warn("%s: IsLong is redundant", name);
  422.     if (flags & flNotLong)
  423.         warn("%s: IsNotLong is redundant", name);
  424.     }
  425.  
  426.     if (flags & (flLong|flNotLong)) {
  427.     enum uselong uselong = itUseLong(it);
  428.  
  429.     /* only give semantic warnings if the user specified something */
  430.  
  431.     if (islong && ((int)uselong <= (int)NotLong))
  432.         warn("%s: doesn't need IsLong", name);
  433.     if (!islong && ((int)uselong >= (int)MustBeLong))
  434.         warn("%s: too big for IsNotLong", name);
  435.     }
  436.  
  437.     return islong;
  438. }
  439.  
  440. /******************************************************
  441.  *  Checks for non-implemented types, conflicting type
  442.  *  flags and whether the long or short form of msg type
  443.  *  descriptor is appropriate. Called after each type statement
  444.  *  is parsed.
  445.  ******************************************************/
  446. static void
  447. itCheckDecl(name, it)
  448.     identifier_t name;
  449.     register ipc_type_t *it;
  450. {
  451.     enum uselong uselong;
  452.  
  453.     it->itName = name;
  454.  
  455.     itCalculateNameInfo(it);
  456.  
  457.     /* do a bit of error checking, mostly necessary because of
  458.        limitations in Mig */
  459.  
  460.     if (it->itVarArray) {
  461.     if ((it->itInTrans != strNULL) || (it->itOutTrans != strNULL))
  462.         error("%s: can't translate variable-sized arrays", name);
  463.  
  464.     if (it->itDestructor != strNULL)
  465.         error("%s: can't destroy variable-sized array", name);
  466.     }
  467.  
  468.     if (it->itVarArray && it->itInLine) {
  469.     if ((it->itElement->itUserType == strNULL) ||
  470.         (it->itElement->itServerType == strNULL))
  471.         error("%s: variable-sized in-line arrays need a named base type",
  472.           name);
  473.     }
  474.  
  475.     /* process the IPC flag specification */
  476.  
  477.     it->itFlags = itCheckFlags(it->itFlags, name);
  478.  
  479.     it->itDeallocate = itCheckDeallocate(it, it->itFlags, d_NO, name);
  480.  
  481.     uselong = itUseLong(it);
  482.     if (uselong == TooLong)
  483.     warn("%s: too big for mach_msg_type_long_t", name);
  484.     it->itLongForm = itCheckIsLong(it, it->itFlags,
  485.                    (int)uselong >= (int)ShouldBeLong, name);
  486. }
  487.  
  488. /*
  489.  *  Pretty-prints translation/destruction/type information.
  490.  */
  491. static void
  492. itPrintTrans(it)
  493.     register ipc_type_t *it;
  494. {
  495.     if (!streql(it->itName, it->itUserType))
  496.     printf("\tCUserType:\t%s\n", it->itUserType);
  497.  
  498.     if (!streql(it->itName, it->itServerType))
  499.     printf("\tCServerType:\t%s\n", it->itServerType);
  500.  
  501.     if (it->itInTrans != strNULL)
  502.        printf("\tInTran:\t\t%s %s(%s)\n",
  503.           it->itTransType, it->itInTrans, it->itServerType);
  504.  
  505.     if (it->itOutTrans != strNULL)
  506.        printf("\tOutTran:\t%s %s(%s)\n",
  507.           it->itServerType, it->itOutTrans, it->itTransType);
  508.  
  509.     if (it->itDestructor != strNULL)
  510.     printf("\tDestructor:\t%s(%s)\n", it->itDestructor, it->itTransType);
  511. }
  512.  
  513. /*
  514.  *  Pretty-prints type declarations.
  515.  */
  516. static void
  517. itPrintDecl(name, it)
  518.     identifier_t name;
  519.     ipc_type_t *it;
  520. {
  521.     printf("Type %s = ", name);
  522.     if (!it->itInLine)
  523.     printf("^ ");
  524.     if (it->itVarArray)
  525.     if (it->itNumber == 0 || it->itIndefinite)
  526.         printf("array [] of ");
  527.     else
  528.         printf("array [*:%d] of ", it->itNumber);
  529.     else if (it->itStruct && ((it->itNumber != 1) ||
  530.                   (it->itInName == MACH_MSG_TYPE_STRING_C)))
  531.     printf("struct [%d] of ", it->itNumber);
  532.     else if (it->itNumber != 1)
  533.     printf("array [%d] of ", it->itNumber);
  534.  
  535.     if (streql(it->itInNameStr, it->itOutNameStr))
  536.     printf("(%s,", it->itInNameStr);
  537.     else
  538.     printf("(%s|%s", it->itInNameStr, it->itOutNameStr);
  539.  
  540.     printf(" %d%s%s%s)\n",
  541.     it->itSize,
  542.     it->itLongForm ? ", IsLong" : "",
  543.     it->itDeallocate == d_YES ? ", Dealloc"
  544.         : it->itDeallocate == d_MAYBE ? ", Dealloc[]"
  545.             : "");
  546.  
  547.     itPrintTrans(it);
  548.  
  549.     printf("\n");
  550. }
  551.  
  552. /*
  553.  *  Handles named type-specs, which can occur in type
  554.  *  declarations or in argument lists.  For example,
  555.  *    type foo = type-spec;    // itInsert will get called later
  556.  *    routine foo(arg : bar = type-spec);    // itInsert won't get called
  557.  */
  558. void
  559. itTypeDecl(name, it)
  560.     identifier_t name;
  561.     ipc_type_t *it;
  562. {
  563.     itCheckDecl(name, it);
  564.  
  565.     if (BeVerbose)
  566.     itPrintDecl(name, it);
  567. }
  568.  
  569. /*
  570.  *  Handles declarations like
  571.  *    type new = name;
  572.  *    type new = inname|outname;
  573.  */
  574. ipc_type_t *
  575. itShortDecl(inname, instr, outname, outstr, defsize)
  576.     u_int inname;
  577.     string_t instr;
  578.     u_int outname;
  579.     string_t outstr;
  580.     u_int defsize;
  581. {
  582.     if (defsize == 0)
  583.     error("must use full IPC type decl");
  584.  
  585.     return itLongDecl(inname, instr, outname, outstr,
  586.               defsize, defsize, flNone);
  587. }
  588.  
  589. /*
  590.  *  Handles declarations like
  591.  *    type new = (name, size, flags...)
  592.  *    type new = (inname|outname, size, flags...)
  593.  */
  594. ipc_type_t *
  595. itLongDecl(inname, instr, outname, outstr, defsize, size, flags)
  596.     u_int inname;
  597.     string_t instr;
  598.     u_int outname;
  599.     string_t outstr;
  600.     u_int defsize;
  601.     u_int size;
  602.     ipc_flags_t flags;
  603. {
  604.     register ipc_type_t *it;
  605.  
  606.     if ((defsize != 0) && (defsize != size))
  607.     warn("IPC type decl has strange size (%u instead of %u)",
  608.          size, defsize);
  609.  
  610.     it = itAlloc();
  611.     it->itInName = inname;
  612.     it->itInNameStr = instr;
  613.     it->itOutName = outname;
  614.     it->itOutNameStr = outstr;
  615.     it->itSize = size;
  616.     if (inname == MACH_MSG_TYPE_STRING_C)
  617.     {
  618.     it->itStruct = FALSE;
  619.     it->itString = TRUE;
  620.     }
  621.     it->itFlags = flags;
  622.  
  623.     itCalculateSizeInfo(it);
  624.     return it;
  625. }
  626.  
  627. static ipc_type_t *
  628. itCopyType(old)
  629.     ipc_type_t *old;
  630. {
  631.     register ipc_type_t *new = itAlloc();
  632.  
  633.     *new = *old;
  634.     new->itName = strNULL;
  635.     new->itNext = itNULL;
  636.     new->itElement = old;
  637.  
  638.     /* size info still valid */
  639.     return new;
  640. }
  641.  
  642. /*
  643.  * A call to itCopyType is almost always followed with itResetType.
  644.  * The exception is itPrevDecl.  Also called before adding any new
  645.  * translation/destruction/type info (see parser.y).
  646.  *
  647.  *    type new = old;    // new doesn't get old's info
  648.  *    type new = array[*:10] of old;
  649.  *            // new doesn't get old's info, but new->itElement does
  650.  *    type new = array[*:10] of struct[3] of old;
  651.  *            // new and new->itElement don't get old's info
  652.  */
  653.  
  654. ipc_type_t *
  655. itResetType(old)
  656.     ipc_type_t *old;
  657. {
  658.     /* reset all special translation/destruction/type info */
  659.  
  660.     old->itInTrans = strNULL;
  661.     old->itOutTrans = strNULL;
  662.     old->itDestructor = strNULL;
  663.     old->itUserType = strNULL;
  664.     old->itServerType = strNULL;
  665.     old->itTransType = strNULL;
  666.     return old;
  667. }
  668.  
  669. /*
  670.  *  Handles the declaration
  671.  *    type new = old;
  672.  */
  673. ipc_type_t *
  674. itPrevDecl(name)
  675.     identifier_t name;
  676. {
  677.     register ipc_type_t *old;
  678.  
  679.     old = itLookUp(name);
  680.     if (old == itNULL)
  681.     {
  682.     error("type '%s' not defined", name);
  683.     return itAlloc();
  684.     }
  685.     else
  686.     return itCopyType(old);
  687. }
  688.  
  689. /*
  690.  *  Handles the declarations
  691.  *    type new = array[] of old;    // number is 0
  692.  *    type new = array[*] of old;    // number is 0
  693.  *    type new = array[*:number] of old;
  694.  */
  695. ipc_type_t *
  696. itVarArrayDecl(number, old)
  697.     u_int number;
  698.     register ipc_type_t *old;
  699. {
  700.     register ipc_type_t *it = itResetType(itCopyType(old));
  701.  
  702.     if (!it->itInLine || it->itVarArray)
  703.     error("IPC type decl is too complicated");
  704.     if (number != 0)
  705.     it->itNumber *= number;
  706.     else {
  707.     /*
  708.      * Send at most 2048 bytes inline.
  709.      */
  710.     u_int    bytes;
  711.  
  712.     bytes = (it->itNumber * it->itSize + 7) / 8;
  713.     it->itNumber = (2048 / bytes) * it->itNumber;
  714.     it->itIndefinite = TRUE;
  715.     }
  716.     it->itVarArray = TRUE;
  717.     it->itStruct = FALSE;
  718.     it->itString = FALSE;
  719.  
  720.     itCalculateSizeInfo(it);
  721.     return it;
  722. }
  723.  
  724. /*
  725.  *  Handles the declaration
  726.  *    type new = array[number] of old;
  727.  */
  728. ipc_type_t *
  729. itArrayDecl(number, old)
  730.     u_int number;
  731.     ipc_type_t *old;
  732. {
  733.     register ipc_type_t *it = itResetType(itCopyType(old));
  734.  
  735.     if (!it->itInLine || it->itVarArray)
  736.     error("IPC type decl is too complicated");
  737.     it->itNumber *= number;
  738.     it->itStruct = FALSE;
  739.     it->itString = FALSE;
  740.  
  741.     itCalculateSizeInfo(it);
  742.     return it;
  743. }
  744.  
  745. /*
  746.  *  Handles the declaration
  747.  *    type new = ^ old;
  748.  */
  749. ipc_type_t *
  750. itPtrDecl(it)
  751.     ipc_type_t *it;
  752. {
  753.     if (!it->itInLine ||
  754.     (it->itVarArray && !it->itIndefinite && (it->itNumber > 0)))
  755.     error("IPC type decl is too complicated");
  756.     it->itNumber = 0;
  757.     it->itIndefinite = FALSE;
  758.     it->itInLine = FALSE;
  759.     it->itStruct = TRUE;
  760.     it->itString = FALSE;
  761.  
  762.     itCalculateSizeInfo(it);
  763.     return it;
  764. }
  765.  
  766. /*
  767.  *  Handles the declaration
  768.  *    type new = struct[number] of old;
  769.  */
  770. ipc_type_t *
  771. itStructDecl(number, old)
  772.     u_int number;
  773.     ipc_type_t *old;
  774. {
  775.     register ipc_type_t *it = itResetType(itCopyType(old));
  776.  
  777.     if (!it->itInLine || it->itVarArray)
  778.     error("IPC type decl is too complicated");
  779.     it->itNumber *= number;
  780.     it->itStruct = TRUE;
  781.     it->itString = FALSE;
  782.  
  783.     itCalculateSizeInfo(it);
  784.     return it;
  785. }
  786.  
  787. /*
  788.  * Treat 'c_string[n]' as
  789.  * 'array[n] of (MSG_TYPE_STRING_C, 8)'
  790.  */
  791. ipc_type_t *
  792. itCStringDecl(count, varying)
  793.     int    count;
  794.     boolean_t varying;
  795. {
  796.     register ipc_type_t *it;
  797.     register ipc_type_t *itElement;
  798.  
  799.     itElement = itShortDecl(MACH_MSG_TYPE_STRING_C,
  800.                 "MACH_MSG_TYPE_STRING_C",
  801.                 MACH_MSG_TYPE_STRING_C,
  802.                 "MACH_MSG_TYPE_STRING_C",
  803.                 8);
  804.     itCheckDecl("char", itElement);
  805.  
  806.     it = itResetType(itCopyType(itElement));
  807.     it->itNumber = count;
  808.     it->itVarArray = varying;
  809.     it->itStruct = FALSE;
  810.     it->itString = TRUE;
  811.  
  812.     itCalculateSizeInfo(it);
  813.     return it;
  814. }
  815.  
  816. extern ipc_type_t *
  817. itMakeCountType()
  818. {
  819.     ipc_type_t *it = itAlloc();
  820.  
  821.     it->itName = "mach_msg_type_number_t";
  822.     it->itInName = MACH_MSG_TYPE_INTEGER_32;
  823.     it->itInNameStr = "MACH_MSG_TYPE_INTEGER_32";
  824.     it->itOutName = MACH_MSG_TYPE_INTEGER_32;
  825.     it->itOutNameStr = "MACH_MSG_TYPE_INTEGER_32";
  826.     it->itSize = 32;
  827.  
  828.     itCalculateSizeInfo(it);
  829.     itCalculateNameInfo(it);
  830.     return it;
  831. }
  832.  
  833. extern ipc_type_t *
  834. itMakePolyType()
  835. {
  836.     ipc_type_t *it = itAlloc();
  837.  
  838.     it->itName = "mach_msg_type_name_t";
  839.     it->itInName = MACH_MSG_TYPE_INTEGER_32;
  840.     it->itInNameStr = "MACH_MSG_TYPE_INTEGER_32";
  841.     it->itOutName = MACH_MSG_TYPE_INTEGER_32;
  842.     it->itOutNameStr = "MACH_MSG_TYPE_INTEGER_32";
  843.     it->itSize = 32;
  844.  
  845.     itCalculateSizeInfo(it);
  846.     itCalculateNameInfo(it);
  847.     return it;
  848. }
  849.  
  850. extern ipc_type_t *
  851. itMakeDeallocType()
  852. {
  853.     ipc_type_t *it = itAlloc();
  854.  
  855.     it->itName = "boolean_t";
  856.     it->itInName = MACH_MSG_TYPE_BOOLEAN;
  857.     it->itInNameStr = "MACH_MSG_TYPE_BOOLEAN";
  858.     it->itOutName = MACH_MSG_TYPE_BOOLEAN;
  859.     it->itOutNameStr = "MACH_MSG_TYPE_BOOLEAN";
  860.     it->itSize = 32;
  861.  
  862.     itCalculateSizeInfo(it);
  863.     itCalculateNameInfo(it);
  864.     return it;
  865. }
  866.  
  867. /*
  868.  *  Initializes the pre-defined types.
  869.  */
  870. void
  871. init_type()
  872. {
  873.     itRetCodeType = itAlloc();
  874.     itRetCodeType->itName = "kern_return_t";
  875.     itRetCodeType->itInName = MACH_MSG_TYPE_INTEGER_32;
  876.     itRetCodeType->itInNameStr = "MACH_MSG_TYPE_INTEGER_32";
  877.     itRetCodeType->itOutName = MACH_MSG_TYPE_INTEGER_32;
  878.     itRetCodeType->itOutNameStr = "MACH_MSG_TYPE_INTEGER_32";
  879.     itRetCodeType->itSize = 32;
  880.     itCalculateSizeInfo(itRetCodeType);
  881.     itCalculateNameInfo(itRetCodeType);
  882.  
  883.     itDummyType = itAlloc();
  884.     itDummyType->itName = "char *";
  885.     itDummyType->itInName = MACH_MSG_TYPE_UNSTRUCTURED;
  886.     itDummyType->itInNameStr = "MACH_MSG_TYPE_UNSTRUCTURED";
  887.     itDummyType->itOutName = MACH_MSG_TYPE_UNSTRUCTURED;
  888.     itDummyType->itOutNameStr = "MACH_MSG_TYPE_UNSTRUCTURED";
  889.     itDummyType->itSize = 32;
  890.     itCalculateSizeInfo(itDummyType);
  891.     itCalculateNameInfo(itDummyType);
  892.  
  893.     itTidType = itAlloc();
  894.     itTidType->itName = "tid_t";
  895.     itTidType->itInName = MACH_MSG_TYPE_INTEGER_32;
  896.     itTidType->itInNameStr = "MACH_MSG_TYPE_INTEGER_32";
  897.     itTidType->itOutName = MACH_MSG_TYPE_INTEGER_32;
  898.     itTidType->itOutNameStr = "MACH_MSG_TYPE_INTEGER_32";
  899.     itTidType->itSize = 32;
  900.     itTidType->itNumber = 6;
  901.     itCalculateSizeInfo(itTidType);
  902.     itCalculateNameInfo(itTidType);
  903.  
  904.     itRequestPortType = itAlloc();
  905.     itRequestPortType->itName = "mach_port_t";
  906.     itRequestPortType->itInName = MACH_MSG_TYPE_COPY_SEND;
  907.     itRequestPortType->itInNameStr = "MACH_MSG_TYPE_COPY_SEND";
  908.     itRequestPortType->itOutName = MACH_MSG_TYPE_PORT_SEND;
  909.     itRequestPortType->itOutNameStr = "MACH_MSG_TYPE_PORT_SEND";
  910.     itRequestPortType->itSize = 32;
  911.     itCalculateSizeInfo(itRequestPortType);
  912.     itCalculateNameInfo(itRequestPortType);
  913.  
  914.     itZeroReplyPortType = itAlloc();
  915.     itZeroReplyPortType->itName = "mach_port_t";
  916.     itZeroReplyPortType->itInName = 0;
  917.     itZeroReplyPortType->itInNameStr = "0";
  918.     itZeroReplyPortType->itOutName = 0;
  919.     itZeroReplyPortType->itOutNameStr = "0";
  920.     itZeroReplyPortType->itSize = 32;
  921.     itCalculateSizeInfo(itZeroReplyPortType);
  922.     itCalculateNameInfo(itZeroReplyPortType);
  923.  
  924.     itRealReplyPortType = itAlloc();
  925.     itRealReplyPortType->itName = "mach_port_t";
  926.     itRealReplyPortType->itInName = MACH_MSG_TYPE_MAKE_SEND_ONCE;
  927.     itRealReplyPortType->itInNameStr = "MACH_MSG_TYPE_MAKE_SEND_ONCE";
  928.     itRealReplyPortType->itOutName = MACH_MSG_TYPE_PORT_SEND_ONCE;
  929.     itRealReplyPortType->itOutNameStr = "MACH_MSG_TYPE_PORT_SEND_ONCE";
  930.     itRealReplyPortType->itSize = 32;
  931.     itCalculateSizeInfo(itRealReplyPortType);
  932.     itCalculateNameInfo(itRealReplyPortType);
  933.  
  934.     itWaitTimeType = itMakeCountType();
  935.     itMsgOptionType = itMakeCountType();
  936. }
  937.  
  938. /******************************************************
  939.  *  Make sure return values of functions are assignable.
  940.  ******************************************************/
  941. void
  942. itCheckReturnType(name, it)
  943.     identifier_t name;
  944.     ipc_type_t *it;
  945. {
  946.     if (!it->itStruct)
  947.     error("type of %s is too complicated", name);
  948.     if ((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) ||
  949.     (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC))
  950.     error("type of %s can't be polymorphic", name);
  951. }
  952.  
  953.  
  954. /******************************************************
  955.  *  Called by routine.c to check that request ports are
  956.  *  simple and correct ports with send rights.
  957.  ******************************************************/
  958. void
  959. itCheckRequestPortType(name, it)
  960.     identifier_t name;
  961.     ipc_type_t *it;
  962. {
  963.     if (((it->itOutName != MACH_MSG_TYPE_PORT_SEND) &&
  964.      (it->itOutName != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
  965.      (it->itOutName != MACH_MSG_TYPE_POLYMORPHIC)) ||
  966.     (it->itNumber != 1) ||
  967.     (it->itSize != 32) ||
  968.     !it->itInLine ||
  969.     it->itDeallocate != d_NO ||
  970.     !it->itStruct ||
  971.     it->itVarArray)
  972.     error("argument %s isn't a proper request port", name);
  973. }
  974.  
  975.  
  976. /******************************************************
  977.  *  Called by routine.c to check that reply ports are
  978.  *  simple and correct ports with send rights.
  979.  ******************************************************/
  980. void
  981. itCheckReplyPortType(name, it)
  982.     identifier_t name;
  983.     ipc_type_t *it;
  984. {
  985.     if (((it->itOutName != MACH_MSG_TYPE_PORT_SEND) &&
  986.      (it->itOutName != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
  987.      (it->itOutName != MACH_MSG_TYPE_POLYMORPHIC) &&
  988.      (it->itOutName != 0)) ||
  989.     (it->itNumber != 1) ||
  990.     (it->itSize != 32) ||
  991.     !it->itInLine ||
  992.     it->itDeallocate != d_NO ||
  993.     !it->itStruct ||
  994.     it->itVarArray)
  995.     error("argument %s isn't a proper reply port", name);
  996. }
  997.  
  998.  
  999. /******************************************************
  1000.  *  Used by routine.c to check that WaitTime is a
  1001.  *  simple bit 32 integer.
  1002.  ******************************************************/
  1003. void
  1004. itCheckIntType(name, it)
  1005.     identifier_t name;
  1006.     ipc_type_t *it;
  1007. {
  1008.     if ((it->itInName != MACH_MSG_TYPE_INTEGER_32) ||
  1009.     (it->itOutName != MACH_MSG_TYPE_INTEGER_32) ||
  1010.     (it->itNumber != 1) ||
  1011.     (it->itSize != 32) ||
  1012.     !it->itInLine ||
  1013.     it->itDeallocate != d_NO ||
  1014.     !it->itStruct ||
  1015.     it->itVarArray)
  1016.     error("argument %s isn't a proper integer", name);
  1017. }
  1018.